/*
 * Copyright (c) 2009-2024 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*============================ INCLUDES ======================================*/

#define __USER_SCENE_FONT_IMPLEMENT__
#include "arm_2d_scene_font.h"

#if defined(RTE_Acceleration_Arm_2D_Helper_PFB)

#include <stdlib.h>
#include <string.h>

#if defined(__clang__)
#   pragma clang diagnostic push
#   pragma clang diagnostic ignored "-Wunknown-warning-option"
#   pragma clang diagnostic ignored "-Wreserved-identifier"
#   pragma clang diagnostic ignored "-Wsign-conversion"
#   pragma clang diagnostic ignored "-Wpadded"
#   pragma clang diagnostic ignored "-Wcast-qual"
#   pragma clang diagnostic ignored "-Wcast-align"
#   pragma clang diagnostic ignored "-Wmissing-field-initializers"
#   pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#   pragma clang diagnostic ignored "-Wmissing-prototypes"
#   pragma clang diagnostic ignored "-Wunused-variable"
#   pragma clang diagnostic ignored "-Wgnu-statement-expression"
#   pragma clang diagnostic ignored "-Wdeclaration-after-statement"
#   pragma clang diagnostic ignored "-Wunused-function"
#   pragma clang diagnostic ignored "-Wmissing-declarations"
#   pragma clang diagnostic ignored "-Wimplicit-int-conversion" 
#elif __IS_COMPILER_ARM_COMPILER_5__
#   pragma diag_suppress 64,177
#elif __IS_COMPILER_IAR__
#   pragma diag_suppress=Pa089,Pe188,Pe177,Pe174
#elif __IS_COMPILER_GCC__
#   pragma GCC diagnostic push
#   pragma GCC diagnostic ignored "-Wformat="
#   pragma GCC diagnostic ignored "-Wpedantic"
#   pragma GCC diagnostic ignored "-Wunused-function"
#   pragma GCC diagnostic ignored "-Wunused-variable"
#   pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
#endif

/*============================ MACROS ========================================*/

#if __GLCD_CFG_COLOUR_DEPTH__ == 8

#   define c_tileCMSISLogo          c_tileCMSISLogoGRAY8

#elif __GLCD_CFG_COLOUR_DEPTH__ == 16

#   define c_tileCMSISLogo          c_tileCMSISLogoRGB565

#elif __GLCD_CFG_COLOUR_DEPTH__ == 32

#   define c_tileCMSISLogo          c_tileCMSISLogoCCCA8888
#else
#   error Unsupported colour depth!
#endif

/*============================ MACROFIED FUNCTIONS ===========================*/
#undef this
#define this (*ptThis)

/*============================ TYPES =========================================*/
/*============================ GLOBAL VARIABLES ==============================*/

extern
const
struct {
    implement(arm_2d_user_font_t);
    arm_2d_char_idx_t tUTF8Table;
}   ARM_2D_FONT_LiberationSansRegular64_A8,
    ARM_2D_FONT_LiberationSansRegular64_A4,
    ARM_2D_FONT_LiberationSansRegular32_A8,
    ARM_2D_FONT_LiberationSansRegular32_A4;

/*============================ PROTOTYPES ====================================*/
/*============================ LOCAL VARIABLES ===============================*/
/*============================ IMPLEMENTATION ================================*/

static void __on_scene_font_load(arm_2d_scene_t *ptScene)
{
    user_scene_font_t *ptThis = (user_scene_font_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __after_scene_font_switching(arm_2d_scene_t *ptScene)
{
    user_scene_font_t *ptThis = (user_scene_font_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene_font_depose(arm_2d_scene_t *ptScene)
{
    user_scene_font_t *ptThis = (user_scene_font_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

    /*--------------------- insert your depose code begin --------------------*/
    

    /*---------------------- insert your depose code end  --------------------*/

    arm_foreach(int64_t,this.lTimestamp, ptItem) {
        *ptItem = 0;
    }
    ptScene->ptPlayer = NULL;
    if (!this.bUserAllocated) {
        __arm_2d_free_scratch_memory(ARM_2D_MEM_TYPE_UNSPECIFIED, ptScene);
    }
}

/*----------------------------------------------------------------------------*
 * Scene font                                                                    *
 *----------------------------------------------------------------------------*/
#if 0  /* deprecated */
static void __on_scene_font_background_start(arm_2d_scene_t *ptScene)
{
    user_scene_font_t *ptThis = (user_scene_font_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene_font_background_complete(arm_2d_scene_t *ptScene)
{
    user_scene_font_t *ptThis = (user_scene_font_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}
#endif


static void __on_scene_font_frame_start(arm_2d_scene_t *ptScene)
{
    user_scene_font_t *ptThis = (user_scene_font_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene_font_frame_complete(arm_2d_scene_t *ptScene)
{
    user_scene_font_t *ptThis = (user_scene_font_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

#if 0
    /* switch to next scene after 3s */
    if (arm_2d_helper_is_time_out(3000, &this.lTimestamp[0])) {
        arm_2d_scene_player_switch_to_next_scene(ptScene->ptPlayer);
    }
#endif
}

static void __before_scene_font_switching_out(arm_2d_scene_t *ptScene)
{
    user_scene_font_t *ptThis = (user_scene_font_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static
IMPL_PFB_ON_DRAW(__pfb_draw_scene_font_handler)
{
    ARM_2D_PARAM(pTarget);
    ARM_2D_PARAM(ptTile);
    ARM_2D_PARAM(bIsNewFrame);

    user_scene_font_t *ptThis = (user_scene_font_t *)pTarget;

    arm_2d_region_t tRenderBox = {.tSize = {600, 320}};

    arm_2d_safe_canvas(ptTile, __test_filed, &tRenderBox) {
    /*-----------------------draw the scene begin-----------------------*/
        arm_2d_dock_with_margin(__test_filed, 20) {

            arm_2d_layout(__dock_region) {

                int16_t iLabelHeight = ARM_2D_FONT_6x8.use_as__arm_2d_font_t.tCharSize.iHeight;

                __item_line_dock_vertical(iLabelHeight + 4) {

                    arm_2d_fill_colour(ptTile, &__item_region, GLCD_COLOR_GRAY(64));

                    arm_lcd_text_set_target_framebuffer((arm_2d_tile_t *)ptTile);
                    arm_lcd_text_set_font(&ARM_2D_FONT_6x8.use_as__arm_2d_font_t);
                    arm_lcd_text_set_draw_region(&__item_region);
                    arm_lcd_text_set_colour(GLCD_COLOR_WHITE, GLCD_COLOR_WHITE);
                    
                    arm_lcd_printf_label(ARM_2D_ALIGN_LEFT, " A 64pixel Font Scaling 0.5f compared with a 32pixel Font");
                }

                __item_line_dock_vertical(60) {

                    arm_2d_helper_draw_box( ptTile,
                                            &__item_region,
                                            1, 
                                            GLCD_COLOR_BLACK, 
                                            64);
                    
                    arm_2d_dock_vertical(__item_region, 40, 20, 20) {

                        arm_2d_helper_draw_box( ptTile,
                                                &__vertical_region,
                                                1, 
                                                GLCD_COLOR_BLUE, 
                                                64);

                        arm_lcd_text_set_target_framebuffer((arm_2d_tile_t *)ptTile);
                        arm_lcd_text_set_draw_region(&__vertical_region);
                        arm_lcd_text_set_colour(GLCD_COLOR_BLACK, GLCD_COLOR_WHITE);

                        /* draw reference */
                        arm_lcd_text_set_scale(0);
                        arm_lcd_printf_to_buffer(
                                (const arm_2d_font_t *)&ARM_2D_FONT_LiberationSansRegular32_A4,
                                "abdilpq"
                            );
                        
                        arm_lcd_text_reset_display_region_tracking();
                        do {
                            arm_lcd_printf_buffer(1);

                        #if 1
                            arm_2d_helper_draw_box(
                                    ptTile, 
                                    arm_lcd_text_get_last_display_region(),
                                    1, 
                                    GLCD_COLOR_RED,
                                    255);
                        #endif
                        } while(arm_lcd_get_residual_text_length_in_buffer());

                        arm_lcd_text_insert_line_space(20);

                        /* draw scaling */
                        arm_lcd_text_set_scale(0.5f);
                        arm_lcd_printf_to_buffer(
                                (const arm_2d_font_t *)&ARM_2D_FONT_LiberationSansRegular64_A4,
                                "abdilpq"
                            );
                        
                        arm_lcd_text_reset_display_region_tracking();
                        do {
                            arm_lcd_printf_buffer(1);

                        #if 1
                            arm_2d_helper_draw_box(
                                    ptTile, 
                                    arm_lcd_text_get_last_display_region(),
                                    1, 
                                    GLCD_COLOR_RED,
                                    255);
                        #endif
                        } while(arm_lcd_get_residual_text_length_in_buffer());

                        arm_lcd_text_set_scale(0.0);

                    }
                }

                __item_line_dock_vertical(iLabelHeight + 4, 0, 0, 20, 0) {

                    arm_2d_fill_colour(ptTile, &__item_region, GLCD_COLOR_GRAY(64));

                    arm_lcd_text_set_target_framebuffer((arm_2d_tile_t *)ptTile);
                    arm_lcd_text_set_font(&ARM_2D_FONT_6x8.use_as__arm_2d_font_t);
                    arm_lcd_text_set_draw_region(&__item_region);
                    arm_lcd_text_set_colour(GLCD_COLOR_WHITE, GLCD_COLOR_WHITE);
                    
                    arm_lcd_printf_label(ARM_2D_ALIGN_LEFT, " A 32pixel Font Scaling 2.0f compared with a 64pixel Font");
                }

                __item_line_dock_vertical_open(100) {

                    arm_2d_helper_draw_box( ptTile,
                                            &__item_region,
                                            1, 
                                            GLCD_COLOR_BLACK, 
                                            64);
                    
                    arm_2d_dock_vertical_open(__item_region, 80, 20, 20) {

                        arm_2d_helper_draw_box( ptTile,
                                                &__vertical_region,
                                                1, 
                                                GLCD_COLOR_BLUE, 
                                                64);

                        arm_lcd_text_set_target_framebuffer((arm_2d_tile_t *)ptTile);
                        arm_lcd_text_set_draw_region(&__vertical_region);
                        arm_lcd_text_set_colour(GLCD_COLOR_BLACK, GLCD_COLOR_WHITE);

                        /* draw reference */
                        arm_lcd_text_set_scale(2.0f);
                        arm_lcd_printf_to_buffer(
                                (const arm_2d_font_t *)&ARM_2D_FONT_LiberationSansRegular32_A4,
                                "abdilpq"
                            );
                        
                        arm_lcd_text_reset_display_region_tracking();
                        do {
                            arm_lcd_printf_buffer(1);

                        #if 1
                            arm_2d_helper_draw_box(
                                    ptTile, 
                                    arm_lcd_text_get_last_display_region(),
                                    1, 
                                    GLCD_COLOR_RED,
                                    255);
                        #endif
                        } while(arm_lcd_get_residual_text_length_in_buffer());

                        arm_lcd_text_insert_line_space(20);

                        /* draw scaling */
                        arm_lcd_text_set_scale(0);
                        arm_lcd_printf_to_buffer(
                                (const arm_2d_font_t *)&ARM_2D_FONT_LiberationSansRegular64_A4,
                                "abdilpq"
                            );
                        
                        arm_lcd_text_reset_display_region_tracking();
                        do {
                            arm_lcd_printf_buffer(1);

                        #if 1
                            arm_2d_helper_draw_box(
                                    ptTile, 
                                    arm_lcd_text_get_last_display_region(),
                                    1, 
                                    GLCD_COLOR_RED,
                                    255);
                        #endif
                        } while(arm_lcd_get_residual_text_length_in_buffer());

                        arm_lcd_text_set_scale(0.0);

                    }
                }



            }

        }

        /* draw text at the top-left corner */
        

        arm_lcd_text_set_scale(0);
        arm_lcd_text_set_target_framebuffer((arm_2d_tile_t *)ptTile);
        arm_lcd_text_set_font(&ARM_2D_FONT_6x8.use_as__arm_2d_font_t);
        arm_lcd_text_set_draw_region(NULL);
        arm_lcd_text_set_colour(GLCD_COLOR_RED, GLCD_COLOR_WHITE);
        arm_lcd_text_location(0,0);
        arm_lcd_puts("Scene font");

    /*-----------------------draw the scene end  -----------------------*/
    }
    ARM_2D_OP_WAIT_ASYNC();

    return arm_fsm_rt_cpl;
}

ARM_NONNULL(1)
user_scene_font_t *__arm_2d_scene_font_init(   arm_2d_scene_player_t *ptDispAdapter, 
                                        user_scene_font_t *ptThis)
{
    bool bUserAllocated = false;
    assert(NULL != ptDispAdapter);

    if (NULL == ptThis) {
        ptThis = (user_scene_font_t *)
                    __arm_2d_allocate_scratch_memory(   sizeof(user_scene_font_t),
                                                        __alignof__(user_scene_font_t),
                                                        ARM_2D_MEM_TYPE_UNSPECIFIED);
        assert(NULL != ptThis);
        if (NULL == ptThis) {
            return NULL;
        }
    } else {
        bUserAllocated = true;
    }

    memset(ptThis, 0, sizeof(user_scene_font_t));

    *ptThis = (user_scene_font_t){
        .use_as__arm_2d_scene_t = {

            /* the canvas colour */
            .tCanvas = {GLCD_COLOR_WHITE}, 

            /* Please uncommon the callbacks if you need them
             */
            .fnOnLoad       = &__on_scene_font_load,
            .fnScene        = &__pfb_draw_scene_font_handler,
            .fnAfterSwitch  = &__after_scene_font_switching,

            /* if you want to use predefined dirty region list, please uncomment the following code */
            //.ptDirtyRegion  = (arm_2d_region_list_item_t *)s_tDirtyRegions,
            
            //.fnOnBGStart    = &__on_scene_font_background_start,        /* deprecated */
            //.fnOnBGComplete = &__on_scene_font_background_complete,     /* deprecated */
            .fnOnFrameStart = &__on_scene_font_frame_start,
            .fnBeforeSwitchOut = &__before_scene_font_switching_out,
            .fnOnFrameCPL   = &__on_scene_font_frame_complete,
            .fnDepose       = &__on_scene_font_depose,

            .bUseDirtyRegionHelper = false,
        },
        .bUserAllocated = bUserAllocated,
    };

    /* ------------   initialize members of user_scene_font_t begin ---------------*/


    /* ------------   initialize members of user_scene_font_t end   ---------------*/

    arm_2d_scene_player_append_scenes(  ptDispAdapter, 
                                        &this.use_as__arm_2d_scene_t, 
                                        1);

    return ptThis;
}


#if defined(__clang__)
#   pragma clang diagnostic pop
#endif

#endif


